package com.atguigu.gulimall.search.thread;

import java.sql.SQLOutput;
import java.util.concurrent.*;

/**
 * @author Yanglinfengkk
 * 多线程测试类
 */
public class ThreadTest {
    public static ExecutorService executor = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("开始.........");
        /*CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("当前线程ID:  " + Thread.currentThread().getId());
            int count = 10 / 2;
            System.out.println("运行结果:  " + count);
        }, executor);*/

        //不接受入参,只有返回值
      /*  CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程ID:  " + Thread.currentThread().getId());
            int count = 10 / 0;
            System.out.println("运行结果:  " + count);
            return count;
        }, executor).whenComplete((res,excption)->{
            //虽然能得到返回信息,但是没法修改返回数据
            System.out.println("异步任务成功完成了.....结果是:"+res+"异常是:"+excption);
        }).exceptionally(throwable -> {
            //可以感知异常,同时返回默认值
            //R apply(T t);
            return 10;
        });*/

      //handle方法 方法执行完成后的处理
      /*  CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程ID:  " + Thread.currentThread().getId());
            int count = 10 / 4;
            System.out.println("运行结果:  " + count);
            return count;
        }, executor).handle((res,thr)->{
            if(res!=null){
                return res*2;
            }
            if(thr!=null){
                return 0;
            }
            return  0;
        });*/
        // R apply(T t, U u);

        /**
         * 线程串行化
         * 1.thenRunAsync   不能获取上一步的执行结果,无返回值
         *          .thenRunAsync(() -> {
         *             System.out.println("任务2启动了....");
         *         }, executor);
         * 2.thenAcceptAsync 能接受上一步结果,但是无法使用返回参数
         *          .thenAcceptAsync(res ->{
         *             System.out.println("任务2启动了...."+res);
         *         },executor);
         * 3.thenApplyAsync 能接受上一步结果,也可以使用返回值
         *          .thenApplyAsync(res -> {
         *             System.out.println("任务2启动了...." + res);
         *             return "Hello Word--->" + res;
         *         }, executor);
         */
        /*CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程ID:  " + Thread.currentThread().getId());
            int count = 10 / 4;
            System.out.println("运行结果:  " + count);
            return count;
        }, executor).thenApplyAsync(res -> {
            System.out.println("任务2启动了...." + res);
            return "Hello Word--->" + res;
        }, executor);
        //R apply(T t);*/

        /**
         * 两个都完成
         */
        /*CompletableFuture<Object> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务1开始:  " + Thread.currentThread().getId());
            int count = 10 / 4;
            System.out.println("任务1运行结果:  ");
            return count;
        }, executor);

        CompletableFuture<Object> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("任务2开始:  " + Thread.currentThread().getId());
            try {
                Thread.sleep(3000);
                System.out.println("任务2执行结果:  ");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello";
        }, executor);*/
        /**
         * 多任务组合
         */
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的图片信息");
            return "hello.jpg";
        }, executor);
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(() -> {
            System.out.println("查询商品的属性");
            return "黑色+256G";
        }, executor);
        CompletableFuture<String> futurDesc = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(3000);
                System.out.println("查询商品介绍信息");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "华为Mate30 Pro";
        }, executor);

       /* CompletableFuture<Void> allOf = CompletableFuture.allOf(futureImg, futureAttr, futurDesc);
        allOf.join();   //等待所有结果完成
        System.out.println("结束........."+futureImg.get() +"---"+futureAttr.get()+"---"+futurDesc.get());*/

        CompletableFuture<Object> anyOf = CompletableFuture.anyOf(futureImg, futureAttr, futurDesc);
        anyOf.get();   //只要有一个任务完成,就返回第一个完成的线程返回值
        System.out.println("结束........."+ anyOf.get());
        /**
         * 两个任务只要有一个完成就执行任务3
         * runAfterEitherAsync  不能获取前两者的返回值,不能更改返回值
         * acceptEitherAsync     可以获取前两者的返回值,不能更改返回指(要求返回值是相同的)
         *
         */
       /* future01.runAfterEitherAsync(future02,()->{
            System.out.println("任务3开始");
        },executor);*/
       /* future01.acceptEitherAsync(future02,(res)->{
            //void accept(T t);
            System.out.println("任务3开始-->"+res);
        },executor);*/
        /*CompletableFuture<String> future = future01.applyToEitherAsync(future02, (res) -> {
            return res.toString() + "->哈哈";
        }, executor);*/

        /*future01.runAfterBothAsync(future02,()->{
            System.out.println("任务3开始");
        },executor);*/      //不能获取前两者的返回值,不能更改返回值

       /* future01.thenAcceptBothAsync(future02,(f1,f2)->{
            //void accept(T t, U u);
            System.out.println("任务3开始...之前的结果:"+f1 +"--->"+f2);
        },executor);*/      //可以获取前两者的返回指,不能更改返回指

        /*CompletableFuture<String> future = future01.thenCombineAsync(future02, (f1, f2) -> {
            //R apply(T t, U u);
            return f1 + ": " + f2 + "->HaHa";
        }, executor);*/

    }



    public void thread(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("开始.........");
        /**
         * 1).继承Thread接口
         *         Thread01 thread = new Thread01();
         *         thread.start();
         * 2).实现Runnable接口
         *         Runnable01 runnable01 = new Runnable01();
         *         new Thread(runnable01).start();
         * 3).实现Callable接口 + FutureTask(可以拿到返回结果,可以批量处理)JDK1.5后添加的
         *         FutureTask<Integer> task = new FutureTask<>(new Callable01());
         *         new Thread(task).start();
         *         //等待整个线程执行完成返回执行结果
         *         Integer integer = task.get();
         *         System.out.println("结束........."+integer);
         * 4).线程池,给线程池直接提交任务[ExecutorService]   Future可以获取到异步结果
         *      1.创建
         *              Executors工具类    service.execute(new Runnable01());
         *              new ThreadPoolExecutor
         *
         *
         */

        //我们以后业务代码里面,以上三种启动线程的方式都不用,将所有的多线程任务交给线程池执行
        //当前系统中的线程池最好不超过3个,每个异步任务,提交给线程池让他去执行就行
        /**
         * 七大参数
         *      corePoolSize    核心线程数[一直存在,除非(allowCoreThreadTimeOut)]:线程池创建好以后就准备就绪的线程数量,就等待来接收异步任务去执行
         *              5个  Thread thread = new  Thread();  thread.start();
         *      maximumPoolSize  最大线程数:控制资源并发
         *      keepAliveTime    存活时间,如果当前线程数量大于核心线程数
         *              释放空闲线程(maximumPoolSize-corePoolSize),只要线程空闲大于指定的keepAliveTime
         *      unit              时间单位
         *      BlockingQueue<Runnable> workQueue   阻塞队列:如果任务有很多,就会将目前多的任务放在队列中里面
         *              只要有线程空闲,就会去队列里面取出新的任务继续执行
         *      threadFactory    线程的创建工厂
         *      RejectedExecutionHandler handler    如果队列满了,按照我们指定的拒绝策略拒绝执行任务
         * 如果不想抛弃还要执行,CallerRunsPolicy拒绝策略
         */
        //new LinkedBlockingQueue<>(10000) 默认是Integer的最大值   指定线程数量/压力测试得到
        ThreadPoolExecutor executor=
                new ThreadPoolExecutor(5,
                        200,
                        10,
                        TimeUnit.SECONDS,
                        new LinkedBlockingQueue<>(10000),
                        Executors.defaultThreadFactory(),
                        new ThreadPoolExecutor.AbortPolicy()
        );

        System.out.println("结束.........");
    }

    /**
     * 继承Thread接口
     */
    public static class Thread01 extends Thread{
        @Override
        public void run() {
            System.out.println("当前线程ID:  "+Thread.currentThread().getId());
            int count=10/2;
            System.out.println("运行结果:  "+count);
        }
    }

    /**
     * 实现Runnable接口
     */
    public static class Runnable01 implements Runnable{
        @Override
        public void run() {
            System.out.println("当前线程ID:  "+Thread.currentThread().getId());
            int count=10/2;
            System.out.println("运行结果:  "+count);
        }
    }
    /**
     * 实现Callable接口 + FutureTask(可以拿到返回结果,可以批量处理)JDK1.5后添加的
     */
    public static class Callable01 implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("当前线程ID:  "+Thread.currentThread().getId());
            int count=10/2;
            System.out.println("运行结果:  "+count);
            return count;
        }
    }
}
